﻿
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Microsoft.Win32;

namespace GDFlacTool.Common
{
    public static class Functions
    {
        public static string GetCurrentFolder(string path)
        {
            if (string.IsNullOrEmpty(path))
                return string.Empty;

            string[] folders = path.Split(Path.DirectorySeparatorChar);

            if(folders.Length > 0)
            {
                return folders[folders.Length - 1];
            }
            
            return string.Empty;
        }

        public static string CreatePlaylist(IList<Track> tracks)
        {
            const string extm3U = "#EXTM3U";
            const string extinf = "#EXTINF";
            int counter = 1;
            var sb = new StringBuilder();

            sb.AppendLine(extm3U);
            sb.AppendLine();

            foreach (Track track in tracks)
            {
                double seconds = Math.Round(TimeSpan.FromTicks(track.TimeTicks).TotalSeconds, 0);

                sb.AppendFormat("{0}:{1}, {2} - {3}", extinf, seconds, track.Artist, track.Title);
                sb.AppendLine();
                sb.Append(track.FullPath);

                if (counter < tracks.Count)
                {
                    sb.AppendLine();
                    sb.AppendLine();

                    counter++;
                }
            }

            return sb.ToString();
        }

        public static void OpenProgram(string programPath, string filePath)
        {
            var startInfo = new ProcessStartInfo {FileName = programPath, Arguments = filePath};
            Process.Start(startInfo);
        }

        public static byte[] ImageToByte(Image img)
        {
            var converter = new ImageConverter();
            return (byte[]) converter.ConvertTo(img, typeof (byte[]));
        }


        public static bool IsFileUsedbyAnotherProcess(string filename)
        {
            try
            {
                File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None);
            }
            catch (IOException)
            {
                return true;
            }
            return false;
        }

        public static bool CheckFileNameForIllegalChars(string filename)
        {
            var invalid = new string(Path.GetInvalidFileNameChars());

            foreach (char c in invalid)
            {
                if (filename.Contains(c))
                {
                    return true;
                }
            }

            return false;
        }

        public static bool CheckPathForIllegalChars(string path)
        {
            var invalid = new string(Path.GetInvalidPathChars());

            foreach (char c in invalid)
            {
                if (path.Contains(c))
                {
                    return true;
                }
            }

            return false;
        }

        public static string RemoveIllegalCharsFileName(string filename)
        {
            var invalid = new string(Path.GetInvalidFileNameChars());
            string retval = filename;

            foreach (char c in invalid)
            {
                if (c == ':')
                {
                    retval = retval.Replace(c, '_');
                }
                else
                {
                    retval = retval.Replace(c.ToString(CultureInfo.InvariantCulture), string.Empty);
                }
            }

            return retval;
        }

        public static string RemoveIllegalCharsPath(string path)
        {
            var invalid = new string(Path.GetInvalidPathChars());
            string retval = path;

            foreach (char c in invalid)
            {
                if (c == ':')
                {
                    retval = retval.Replace(c, '_');
                }
                else
                {
                    retval = retval.Replace(c.ToString(CultureInfo.InvariantCulture), string.Empty);
                }
            }

            return retval;
        }

        public static bool IsUrlAvailable(string url)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);

                using (HttpWebResponse rsp = (HttpWebResponse) req.GetResponse())
                {
                    if (rsp.StatusCode == HttpStatusCode.OK)
                    {
                        return true;
                    }
                }
            }
            catch (WebException)
            {
                // Eat it because all we want to do is return false
            }

            // Otherwise
            return false;
        }

        public static bool CheckUrl(string url)
        {
            try
            {
                WebRequest req = WebRequest.Create(url);

                WebResponse res = req.GetResponse();

                return true;
            }
            catch (WebException)
            {
                return false;
            }
            catch (UriFormatException)
            {
                return false;
            }
        }

        private static string GetDefaultBrowserPath()
        {
            const string key = @"htmlfile\shell\open\command";

            RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(key, false);

            if (registryKey != null)
            {
                return ((string) registryKey.GetValue(null, null)).Split('"')[1];
            }

            return string.Empty;
        }

        public static bool OpenUrl(string url)
        {
            string defaultBrowser = GetDefaultBrowserPath();
            if (!string.IsNullOrEmpty(defaultBrowser) && !string.IsNullOrEmpty(url))
            {
                if (CheckUrl(url))
                {
                    try
                    {
                        var p = new Process {StartInfo = {FileName = defaultBrowser, Arguments = url}};

                        p.Start();

                        return true;
                    }
                    catch (Exception)
                    {
                        return false;
                    }
                }
            }

            return false;
        }

        public static string CommonPrefix(string[] ss)
        {
            if (ss.Length == 0)
            {
                return "";
            }

            if (ss.Length == 1)
            {
                return ss[0];
            }

            int prefixLength = 0;

            foreach (char c in ss[0])
            {
                foreach (string s in ss)
                {
                    if (s.Length <= prefixLength || s[prefixLength] != c)
                    {
                        return ss[0].Substring(0, prefixLength);
                    }
                }
                prefixLength++;
            }

            return ss[0]; // all strings identical 
        }


        public static byte[] GetImageByteArray(string path)
        {
            FileStream fs = null;
            MemoryStream ms = new MemoryStream();

            try
            {
                fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);

                fs.CopyTo(ms);

                return ms.ToArray();
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                if (fs != null) fs.Close();
                ms.Close();
            }
        }

        public static string InvertCasing(string text)
        {
            if (text == null)
                return String.Empty;

            StringBuilder sb = new StringBuilder();
            foreach (char c in text)
            {
                if (Char.IsLower(c))
                    sb.Append(Char.ToUpper(c));
                else if (Char.IsUpper(c))
                    sb.Append(Char.ToLower(c));
                else
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        public static bool ValidateKeyChar(char key)
        {
            // Try converting the introduced char value to a byte value
            byte i;
            bool parsed = Byte.TryParse(key.ToString(), out i);
            bool val;

            //If convresion succeeded, show allow character.
            if (parsed)
            {
                val = false;
            }
                // If the conversion did not succeed, check if the pressed
                // button was Backspace (char code is 8) or Delete (char code is 46).
            else
            {
                switch (Convert.ToInt32(key))
                {
                    case 8:
                        val = false; // If Backspace, allow char.
                        break;
                    case 46:
                        val = false; // If Delete, allow char.
                        break;
                    default:
                        val = true;
                        break;
                }
            }
            return val;
        }

        public static string ShortenName(string pathname, int maxLength)
        {
            if (pathname.Length <= maxLength)
            {
                return pathname;
            }

            string root = Path.GetPathRoot(pathname);

            if (root != null)
            {
                if (root.Length > 3)
                {
                    root += Path.DirectorySeparatorChar;
                }
            }

            string[] elements = pathname.Substring(root.Length).Split(Path.DirectorySeparatorChar,
                                                                      Path.AltDirectorySeparatorChar);

            int filenameIndex = elements.GetLength(0) - 1;

            if (elements.GetLength(0) == 1) // pathname is just a root and filename
            {
                if (elements[0].Length > 5) // long enough to shorten
                {
                    // if path is a UNC path, root may be rather long
                    if (root.Length + 6 >= maxLength)
                    {
                        return root + elements[0].Substring(0, 3) + "...";
                    }

                    return pathname.Substring(0, maxLength - 3) + "...";
                }
            }
            else if ((root.Length + 4 + elements[filenameIndex].Length) > maxLength)
                // pathname is just a root and filename
            {
                root += "...\\";

                int len = elements[filenameIndex].Length;

                if (len < 6)
                {
                    return root + elements[filenameIndex];
                }

                if ((root.Length + 6) >= maxLength)
                {
                    len = 3;
                }
                else
                {
                    len = maxLength - root.Length - 3;
                }

                return root + elements[filenameIndex].Substring(0, len) + "...";
            }
            else if (elements.GetLength(0) == 2)
            {
                return root + "...\\" + elements[1];
            }
            else
            {
                int len = 0;
                int begin = 0;

                for (int i = 0; i < filenameIndex; i++)
                {
                    if (elements[i].Length > len)
                    {
                        begin = i;
                        len = elements[i].Length;
                    }
                }

                int totalLength = pathname.Length - len + 3;
                int end = begin + 1;

                while (totalLength > maxLength)
                {
                    if (begin > 0)
                        totalLength -= elements[--begin].Length - 1;

                    if (totalLength <= maxLength)
                        break;

                    if (end < filenameIndex)
                        totalLength -= elements[++end].Length - 1;

                    if (begin == 0 && end == filenameIndex)
                        break;
                }

                // assemble final string

                for (int i = 0; i < begin; i++)
                {
                    root += elements[i] + '\\';
                }

                root += "...\\";

                for (int i = end; i < filenameIndex; i++)
                {
                    root += elements[i] + '\\';
                }

                return root + elements[filenameIndex];
            }

            return pathname;
        }

        public static string TranslateReleaseType(int index)
        {
            switch (index)
            {
                case 1:
                    return "Album";
                case 2:
                    return "Anthology";
                case 3:
                    return "Audio Book";
                case 4:
                    return "Bootleg";
                case 5:
                    return "Compilation";
                case 6:
                    return "Digital";
                case 7:
                    return "DVD";
                case 8:
                    return "EP";
                case 9:
                    return "Live Performance";
                case 10:
                    return "Sampler";
                case 11:
                    return "Single/Maxi";
                case 12:
                    return "Sound Effects";
                case 13:
                    return "Soundtrack";
                case 14:
                    return "Video";
                default:
                    return string.Empty;
            }
        }

        public static string GetFolderArtSizeFromFile(string path)
        {
            FileInfo fileInfo = new FileInfo(path);

            long size = fileInfo.Length;

            int[] limits = new int[] {1024*1024*1024, 1024*1024, 1024};
            string[] units = new string[] {"GB", "MB", "KB"};

            for (int i = 0; i < limits.Length; i++)
            {
                if (size >= limits[i])
                    return String.Format("{0:#,##0.0} " + units[i], ((double) size/limits[i]));
            }

            return String.Format("{0} bytes", size);
        }

        public static string GetFileArtSizeFromBytes(long bytes)
        {
            long size = bytes;
            int[] limits = new[] {1024*1024*1024, 1024*1024, 1024};
            string[] units = new[] {"GB", "MB", "KB"};

            for (int i = 0; i < limits.Length; i++)
            {
                if (size >= limits[i])
                    return String.Format("{0:#,##0.#} " + units[i], ((double) size/limits[i]));
            }

            return String.Format("{0} bytes", size);
        }

    }
}
